#pragma once

#include "FiringEvent.h"

namespace SpikingNeuronLib
{
	// LinkedEventPair: a pair of linked firing events of the form (preFiringEvent), (postFiringEvent), connectionDelay, connectionWeight, layer)
	public ref struct LinkedEventPair
	{
	public:
		property FiringEvent PreEvent;
		property FiringEvent PostEvent;
		property double ConnectionWeight;
		property int ConnectionDelay;
		property int Layer;
		property double LinkProbability;

		LinkedEventPair(FiringEvent preEvent, FiringEvent postEvent, double connectionWeight, double linkProbability)
		{
			PreEvent = preEvent;
			PostEvent = postEvent;
			ConnectionWeight = connectionWeight;
			ConnectionDelay = 0;
			Layer = 0;
			LinkProbability = linkProbability;
		}

		LinkedEventPair(FiringEvent preEvent, FiringEvent postEvent, double connectionWeight, int connectionDelay, int layer)
		{
			PreEvent = preEvent;
			PostEvent = postEvent;
			ConnectionWeight = connectionWeight;
			ConnectionDelay = connectionDelay;
			Layer = layer;
			LinkProbability = 0.0;
		}

		LinkedEventPair(FiringEvent preEvent, FiringEvent postEvent, double connectionWeight, int connectionDelay, int layer, double linkProbability)
		{
			PreEvent = preEvent;
			PostEvent = postEvent;
			ConnectionWeight = connectionWeight;
			ConnectionDelay = connectionDelay;
			Layer = layer;
			LinkProbability = linkProbability;
		}

		Tuple<Tuple<int, int>^, Tuple<int, int>^, double, int, int, double>^ AsTuple() {
			Tuple<int, int>^ preEvent = gcnew Tuple<int, int>(PreEvent.Time, PreEvent.NeuronIndex);
			Tuple<int, int>^ postEvent = gcnew Tuple<int, int>(PostEvent.Time, PostEvent.NeuronIndex);

			return gcnew Tuple<Tuple<int, int>^, Tuple<int, int>^, double, int, int, double>(preEvent, postEvent, ConnectionWeight, ConnectionDelay, Layer, LinkProbability);
		}

		virtual String^ ToString() override {
			return String::Format("({0}, {1}), ({2}, {3}) {4} {5} {6} {7}",
				PreEvent.Time, PreEvent.NeuronIndex,
				PostEvent.Time, PostEvent.NeuronIndex,
				ConnectionDelay, ConnectionWeight, Layer, LinkProbability);
		}

		String^ ToSimpleString() {
			return String::Format("{0} {1} {2} {3} {4} {5} {6} {7}",
				PreEvent.Time, PreEvent.NeuronIndex,
				PostEvent.Time, PostEvent.NeuronIndex,
				ConnectionDelay, ConnectionWeight, Layer, LinkProbability);
		}
	};
}
